#include "config.h"
#include <fstream>
#include <cassert>
#include <cJSON.h>
#include <logger.h>
#include <httphelper.h>
#include <loradevice.h>
#include <oiltanks.h>
#include <oiltrans.h>

namespace terminals
{
    using namespace cores::common;
    using namespace cores::devices;

    string TConfigure::globalConfigFileName = "./config/service_config.json";

    // 定义全局变量
    TConfigure gConfigure;

    TConfigure::TConfigure() : Configure()
    {
    }

    TConfigure::~TConfigure()
    {
    }

    void TConfigure::loadConfigInfo()
    {
        ifstream config_file(TConfigure::globalConfigFileName);
        assert(config_file.is_open());

        string json_data;
        string line;

        while (getline(config_file, line))
        {
            json_data += line + "\n";
        }

        cJSON *json_root = cJSON_Parse(json_data.c_str());

        // 读取配置文件中的加油站编号
        auto item = cJSON_GetObjectItem(json_root, "station_code");
        assert(item);
        addConfigItem("station_code", string(item->valuestring));
        XLOG("success to read station_code = \"%s\"", item->valuestring);

        // 读取配置文件中的区域码
        item = cJSON_GetObjectItem(json_root, "dept_code");
        assert(item);
        addConfigItem("dept_code", string(item->valuestring));
        XLOG("success to read dept_code = \"%s\"", item->valuestring);

        // 读取配置文件中的网络获取api路径
        item = cJSON_GetObjectItem(json_root, "config_api_url");
        assert(item);
        addConfigItem("config_api_url", string(item->valuestring));
        XLOG("success to read config_api_url = \"%s\"", item->valuestring);

        // 读取LoraData话题名称
        item = cJSON_GetObjectItem(json_root, "lora_data_topic");
        assert(item);
        addConfigItem("lora_data_topic", string(item->valuestring));
        XLOG("success to read lora_data_topic = \"%s\"", item->valuestring);

        // 读取报警信息的加密字符
        item = cJSON_GetObjectItem(json_root, "warming_token");
        assert(item);
        addConfigItem("warming_token", string(item->valuestring));
        XLOG("success to read warming_token = \"%s\"", item->valuestring);

        // 读取是否需要校验CRC值
        item = cJSON_GetObjectItem(json_root, "crc_check");
        assert(item);
        addConfigItem("crc_check", item->valueint == 1);
        XLOG("success to read crc_check = \"%s\"", item->valueint == 1 ? "true" : "false");

        // 读取是否需要自动升级
        item = cJSON_GetObjectItem(json_root, "auto_upgrade");
        assert(item);
        addConfigItem("auto_upgrade", item->valueint == 1);
        XLOG("success to read auto_upgrade = \"%s\"", item->valueint == 1 ? "true" : "false");

        // 获取服务版本号
        item = cJSON_GetObjectItem(json_root, "service_version");
        if (item != nullptr)
            addConfigItem("service_version", item->valuestring);
        else
            addConfigItem("service_version", "1.0");

        // 读取是否更新配置标志
        item = cJSON_GetObjectItem(json_root, "is_update_config");
        if (item != nullptr)
            addConfigItem("is_update_config", item->valueint == 1 ? true : false);
        else
            addConfigItem("is_update_config", false);

        item = cJSON_GetObjectItem(json_root, "expired_time");
        if (item != nullptr)
            addConfigItem("expired_time", item->valueint);
        else
            addConfigItem("expired_time", 60);

        // 以毫秒为单位
        item =cJSON_GetObjectItem(json_root, "lora_expired_time");
        if (item != nullptr)
            addConfigItem("lora_expired_time", item->valueint);
        else
            addConfigItem("lora_expired_time", 3000);

        cJSON_Delete(json_root);

        loadWebConfig();
    }

    void TConfigure::loadWebConfig()
    {
        // 获取站点相关信息
        auto api_json_str = HttpHelper::GetConfigFromApi(Configure::toString("station_code"));
        XLOG("获取站点信息:%s", api_json_str);

        cJSON *json_root = cJSON_Parse(api_json_str.c_str());

        // 获取数据上传时间间隔
        auto item = cJSON_GetObjectItem(json_root, "to_cloud_duration");
        assert(item);
        Configure::addConfigItem("to_cloud_duration", item->valueint);
        XLOG("成功获取站点的数据上传时间:%d秒", item->valueint);

        item = cJSON_GetObjectItem(json_root, "lora_token_duration");
        assert(item);
        Configure::addConfigItem("lora_token_duration", item->valueint);
        XLOG("成功获取站点LORA令牌循环时间:%d秒", item->valueint);

        // 读取端口号
        item = cJSON_GetObjectItem(json_root, "dev_name");
        assert(item);
        Configure::addConfigItem("dev_name", item->valuestring);
        XLOG("成功读取Lora端口号:%s", item->valuestring);

        // 读取波特率
        item = cJSON_GetObjectItem(json_root, "baud");
        assert(item);
        Configure::addConfigItem("baud", item->valueint);

        // 读取波特率
        item = cJSON_GetObjectItem(json_root, "data_bit");
        assert(item);
        Configure::addConfigItem("data_bit", item->valueint);

        // 读取端口号
        item = cJSON_GetObjectItem(json_root, "llq_dev_name");
        assert(item);
        Configure::addConfigItem("llq_dev_name", item->valuestring);

        // 读取波特率
        item = cJSON_GetObjectItem(json_root, "llq_baud");
        assert(item);
        Configure::addConfigItem("llq_baud", item->valueint);

        // 读取波特率
        item = cJSON_GetObjectItem(json_root, "llq_data_bit");
        assert(item);
        Configure::addConfigItem("llq_data_bit", item->valueint);

        // 读取波特率
        item = cJSON_GetObjectItem(json_root, "is_test");
        assert(item);
        auto type = item->valueint;
        Configure::addConfigItem("is_test", (type == 1));

        // 读取socketIp
        item = cJSON_GetObjectItem(json_root, "data_server_ip");
        assert(item);
        Configure::addConfigItem("dataServerIp", item->valuestring);

        // 读取socketPort
        item = cJSON_GetObjectItem(json_root, "data_server_port");
        assert(item);
        Configure::addConfigItem("dataServerPort", item->valueint);

        // 读取报警信息的链接
        item = cJSON_GetObjectItem(json_root, "warming_url");
        assert(item);
        Configure::addConfigItem("warming_url", item->valuestring);

        // 读取设备名词（数组）
        cJSON *json_array_ = cJSON_GetObjectItemCaseSensitive(json_root, "device_names");
        if (!cJSON_IsArray(json_array_))
        {
            XERROR("device_names is not an array");
            cJSON_Delete(json_root);
            assert(nullptr);
        }

        cores::devices::LoraDeviceManager::Clear();

        cJSON *json_array = cJSON_GetObjectItemCaseSensitive(json_root, "device_names");
        if (cJSON_IsArray(json_array))
        {
            auto arr_size = cJSON_GetArraySize(json_array);
            // 从数据库中读取Lora设备的数据序号
            using namespace cores::database::terminal;

            for (auto i = 0; i < arr_size; i++)
            {
                auto arr_item = cJSON_GetArrayItem(json_array, i);
                if (arr_item == nullptr)
                    continue;

                // OilTransReq req_item{
                //     (uint16_t)cJSON_GetObjectItem(arr_item, "lora_id")->valueint,
                //     (uint8_t)cJSON_GetObjectItem(arr_item, "nozzle_code")->valueint,
                //     (uint8_t)cJSON_GetObjectItem(arr_item, "category")->valueint,
                //     (uint8_t)cJSON_GetObjectItem(arr_item, "screen_type")->valueint,
                //     (uint8_t)cJSON_GetObjectItem(arr_item, "rate")->valueint,
                //     0,
                //     false,
                //     false,
                //     0,
                //     0,
                //     false};
                uint16_t t_lora_id = cJSON_GetObjectItem(arr_item, "lora_id")->valueint;
                uint8_t t_nozzle_code = cJSON_GetObjectItem(arr_item, "nozzle_code")->valueint;
                auto sn = OilTrans::getSerialNumberDataS(t_lora_id, t_nozzle_code);

                if (sn.empty())
                {
                    sn.push_back({t_lora_id, t_nozzle_code, 0, 0});
                    OilTrans::addSerialNumberRecordS(sn[0]);
                }
                else
                {
                    XLOG("success to get (lora id:%d\tnozzle code:%d\ttrans_sn:%d\ttax_sn:%d", sn[0].lora_id, sn[0].nozzle_code, sn[0].trans_max_num, sn[0].tax_max_num);
                }

                LoraDeviceManager::Add({t_lora_id,                                                       //(uint16_t)cJSON_GetObjectItem(arr_item, "lora_id")->valueint,
                                        t_nozzle_code,                                                   //(uint8_t)cJSON_GetObjectItem(arr_item, "nozzle_code")->valueint,
                                        (uint8_t)cJSON_GetObjectItem(arr_item, "category")->valueint,    // 油品
                                        (uint8_t)cJSON_GetObjectItem(arr_item, "screen_type")->valueint, // 屏类型
                                        (uint8_t)cJSON_GetObjectItem(arr_item, "rate")->valueint,        // 编码器比值
                                        (sn.empty() ? uint16_t(0) : sn[0].trans_max_num),                            // 0,              //请求数据编号
                                        (sn.empty() ? uint16_t(0) : sn[0].tax_max_num),                              // 0,              //请求编码器数据编号
                                        false,
                                        false,
                                        0,
                                        0,
                                        false});
            }
        }

        cores::devices::OilTanksManager::Clear();
        json_array = cJSON_GetObjectItemCaseSensitive(json_root, "oil_tanks");
        if (cJSON_IsArray(json_array))
        {
            auto arr_size = cJSON_GetArraySize(json_array);
            for (auto i = 0; i < arr_size; i++)
            {
                auto arr_item = cJSON_GetArrayItem(json_array, i);
                if (arr_item == nullptr)
                    continue;

                uint16_t oil_address = (1000 - 1) + i * 12;
                cores::devices::OilTanksManager::Add({(uint8_t)cJSON_GetObjectItem(arr_item, "tank_code")->valueint,
                                                      (uint8_t)cJSON_GetObjectItem(arr_item, "category")->valueint,
                                                      oil_address,
                                                      false,
                                                      false,
                                                      0,
                                                      0});
            }
        }

        cJSON_Delete(json_root);
    }
}